12 腾讯-一面-企业微信团队
> Last Format Time:6/12/2026 21:03:57
这次面的是上一个部门的兄弟部门,主要是移动端,也有在维护一个企业微信后台web应用。
代码(30min)
- 比较版本号,写的比较啰嗦,对于越界的数组的值使用空值合并
- 不用sort进行排序,只有0,1,2
提问
- 跨域有关的问题。为什么要有这个限制,什么会被限制呢?
- cros的头配置是怎么样的,浏览器是怎么判断是否放行的
- 垂直水平居中的实现,越多越好
- 绝对和相对的为什么要这么设置,transsmsm的是什么,只设置这些就够了吗,相对为什么会跟绝对,他们之间的关系是怎么样的。
- box-sizing的值,除了border的计算区别,content-box与border-box还有什么区别呢
- 一个监控系怎么构建的,当页面报错的时候,这个错误是怎么捕获的呢?
- skill与mcp的区别
- skill是怎么样的
- rag的词嵌入向量化是怎么做的
- 你如何来验收skill的效果,尤其是召回率
- 你知道skill与渐进式披露吗,那skill的meta信息、其中的内容与渐进式披露是怎么组织的,agent是怎么实现的呢
反问
- 我们目前正在做的agent
UI还原方面: spec coding,使用figma先构建一个静态的页面,然后人工介入,agent改正后验收,进行影响面测评,上线。
针对你面试中遇到的这些前端与AI Agent相关的深度提问,我为你整理了一份结构清晰、逻辑严谨的标准回答参考。你可以结合自己的实际项目经验,用这些核心要点来组织语言。
跨域有关的问题
为什么要有这个限制,什么会被限制呢?
- 为什么限制: 跨域限制的核心是浏览器的同源策略(Same-Origin Policy, SOP)。这并非Bug,而是浏览器内置的核心安全基石。它的根本目的是防范 CSRF(跨站请求伪造)、XSS(跨站脚本攻击)等恶意攻击,保护用户的隐私数据(如Cookie、LocalStorage)不被非同源的恶意网站窃取或篡改。
- 什么被限制: 同源策略要求两个URL的协议、域名、端口号三者必须完全一致。如果不同源,浏览器会限制:
- 无法读取非同源网页的 DOM 节点(如 iframe 内容)。
- 无法读取非同源的 Cookie、LocalStorage 和 IndexDB。
- 无法向非同源地址发送 AJAX/Fetch 请求(或者请求能发出,但浏览器拦截了响应结果,JS无法读取)。
CORS的头配置是怎么样的,浏览器是怎么判断是否放行的?
- 核心头配置: 服务器通过在响应头中配置
Access-Control-Allow-Origin来告知浏览器允许哪些源访问。 - 浏览器判断逻辑: 浏览器将跨域请求分为两类:
- 简单请求(直接放行): 请求方法是 GET/POST/HEAD,且 Content-Type 为
text/plain、multipart/form-data或application/x-www-form-urlencoded。浏览器直接发起真实请求,然后校验响应头中的跨域字段,校验通过则放行数据。 - 预检请求(复杂请求): 只要不满足简单请求的条件(如使用了 PUT/DELETE 方法,或携带了自定义 Token 请求头,或 Content-Type 为
application/json),浏览器会自动先发起一个 OPTIONS 试探请求。服务器校验通过并返回允许跨域的响应头后,浏览器才会发起真实的业务请求。
- 简单请求(直接放行): 请求方法是 GET/POST/HEAD,且 Content-Type 为
垂直水平居中的实现
实现方式(越多越好)
- Flex 布局(最常用): 父元素设置
display: flex; justify-content: center; align-items: center;。 - 绝对定位 + Transform: 父元素
position: relative,子元素position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);。 - 绝对定位 + Margin Auto: 父元素
position: relative,子元素position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto;。 - Grid 布局: 父元素
display: grid; justify-content: center; align-items: center;。 - 绝对定位 + 负 Margin(需知子元素宽高): 子元素
position: absolute; top: 50%; left: 50%; margin-top: -子元素高度的一半; margin-left: -子元素宽度的一半;。
绝对和相对的为什么要这么设置,transform 是什么,它们之间的关系?
- 相对与绝对的关系: 设置父元素
position: relative是为了给子元素的position: absolute建立一个定位基准(包含块)。如果父元素没有设置相对定位(或其他非 static 定位),子元素的绝对定位会一直向上寻找,最终相对于浏览器窗口(body)进行定位,导致布局错乱。 - Transform 的作用:
transform: translate(-50%, -50%)的作用是基于子元素自身的宽度和高度,向左和向上各移动自身尺寸的 50%。这弥补了top: 50%; left: 50%;只是将子元素的左上角定位到父元素中心的偏差,从而实现完美的视觉居中。 - 只设置这些够吗: 使用
transform方案不需要知道子元素的具体宽高,兼容性较好,通常只设置这些就够了。但如果使用负 Margin 方案,就必须明确知道子元素的宽高。
box-sizing 的值
content-box 与 border-box 的区别
- content-box(默认值):
width和height仅包含内容区。元素的实际渲染宽度 =width + padding + border。这意味着如果你设置width: 100px,再加上padding和border,元素在页面上占据的实际空间会大于 100px。 - border-box:
width和height包含了内容区 + 内边距(padding) + 边框(border)。如果你设置width: 100px,无论padding和border是多少,元素在页面上占据的实际空间永远是 100px,内容区的宽度会自动收缩(内容宽度 =width - padding - border)。 - 核心区别:
border-box让元素的尺寸控制更加直观和可预测,特别是在响应式布局中,能极大减少因计算 padding 和 border 带来的布局溢出问题。
其实除了大家最熟悉的 border 之外,这两种盒模型在 padding(内边距) 的计算上也有同样的区别,而且它们在实际开发中对布局的影响完全不同。
简单来说,这两种盒模型分别是 标准盒模型(content-box) 和 IE盒模型(border-box)。
它们的核心区别就在于:当你给一个元素设置了固定的 width 和 height 时,浏览器到底把哪些部分算进这个尺寸里?
标准盒模型 (content-box)
这是浏览器默认的模式。
- 计算规则: 你设置的
width和height仅仅 是内容区(content)的大小。 - 实际占位: 元素在页面上实际占据的宽/高 =
width + padding + border + margin。 - 直观感受: 只要你给元素加了 padding 或 border,元素就会被"撑大",实际尺寸会大于你写的 width。
IE盒模型 (border-box)
这是现代前端开发中更推荐使用的模式。
- 计算规则: 你设置的
width和height包含了 内容区(content)、内边距(padding)和边框(border)。 - 实际占位: 元素在页面上实际占据的宽/高 =
width + margin。(注意:padding 和 border 被包含在 width 里了) - 直观感受: 无论你给元素加多厚的 border 或多大的 padding,只要 width 不变,元素在页面上占据的视觉大小就永远不变,它会自动向内挤压内容区(content)的空间。
一张表看懂区别
假设你写了一个 CSS:width: 200px; padding: 20px; border: 5px solid black;
| 特性 | 标准盒模型 (content-box) | IE盒模型 (border-box) |
|---|---|---|
| width 的含义 | 仅代表内容区的宽度 | 代表 border + padding + content 的总宽度 |
| 元素实际渲染宽度 | 200 + 20_2 + 5_2 = 250px | 固定为 200px |
| 内容区(content)实际宽度 | 固定为 200px | 200 - 20_2 - 5_2 = 150px (自动计算) |
| 增加 padding/border 的影响 | 元素会被撑大,容易破坏布局 | 元素大小不变,内容区变小 |
实际开发中的建议
在现代前端开发(尤其是写响应式布局或栅格系统)时,强烈建议全局使用 IE盒模型 (border-box)。
因为使用 border-box 更符合人类的直觉:你写 width: 50%,它就是占一半,不管里面有没有 padding,都不会因为加了内边距就导致两个 50% 的元素换行。
通常我们会在全局 CSS 里加这样一段代码来统一规范:
*, *::before, *::after {
box-sizing: border-box;
}
这样做之后,你就不用每次写样式时都在心里做加减法,也不用担心 padding 把布局撑爆了。
前端监控系统如何构建与错误捕获
监控系统的构建
一个完整的前端监控体系通常包含错误监控(JS错误、资源加载失败、接口错误)、性能监控(首屏时间、页面加载耗时)、用户行为监控(点击、路由跳转)以及业务指标监控。
页面报错时的错误捕获方式
- 全局 JS 运行时错误: 监听
window.addEventListener('error', ...)事件,可以捕获未处理的同步代码异常、语法错误以及图片等资源的加载失败。 - Promise 未捕获异常: 监听
window.addEventListener('unhandledrejection', ...)事件,专门捕获异步代码中未被catch的 Promise 拒绝。 - 资源加载失败: 通过在
window上捕获error事件,并判断event.target的标签名(如SCRIPT、LINK、IMG)来记录缺失的资源路径。 - 接口请求错误: 通过重写(劫持)原生的
fetch或XMLHttpRequest方法,在请求返回非 200 状态或网络异常时,收集接口报错信息。 - 框架级错误: 如果使用 Vue 或 React,还可以利用框架提供的错误边界(如 Vue 的
errorCaptured或 React 的componentDidCatch)来捕获组件渲染阶段的错误。
Skill 与 MCP 的区别
MCP (Model Context Protocol)
本质是一套标准化的接驳协议。它提供了一个统一的协议转换层(Server),让大模型能以标准化的方式(如 JSON-RPC)与外部系统、API 或数据源进行交互。MCP 解决的是"如何连接工具"的问题。
Skill
本质是一个Sub-agent(子智能体)的包装,或者说是一套"工作手册"。它允许开发者用自然语言(Markdown)来定义复杂的任务流程、领域知识和最佳实践。Skill 解决的是"如何编排工具完成复杂任务"的问题。
关系
两者存在一定的竞争关系,但更多是互补。MCP 负责把工具标准化地暴露出来,而 Skill 可以在其内部逻辑中调用 MCP 提供的工具来完成多步骤的复杂任务。
Skill 是怎么样的
定义
Skill(技能)是 Anthropic 提出的一种标准扩展规范,你可以把它想象成一个打包好的**"技能包"**。它通常是一个包含 SKILL.md 文件的文件夹。
构成
一个 Skill 包含元数据(名称、描述)、详细的操作指令(SKILL.md 中的自然语言流程)、以及可选的配套资源(如 Python 脚本、参考文档、模板文件等)。
作用
它将特定任务的流程、规则和工具调用方式封装起来。当 AI 遇到相关需求时,能像专家一样,按照预设的"说明书"有条不紊地调用工具、执行脚本,从而精准地完成专业任务。
RAG 的词嵌入向量化是怎么做的
在 RAG(检索增强生成)中,词嵌入(Embedding)的核心是将文本映射为高维向量,以衡量语义相似性。
- 早期方法: 如 Word2Vec、GloVe,它们生成的是静态向量(一词一向量),无法处理多义词在不同语境下的差异。
- 现代主流方法(如 BERT): 基于 Transformer 的编码器架构,利用自注意力机制(Self-Attention)。它能同时捕捉词与上下文中所有词的关联,生成动态向量(一词多向量)。例如,"刀"在"切菜的刀"和"李元芳的刀"中,会根据上下文生成不同的向量表示,从而更精准地捕捉深层语义。
- 流程: 将本地文档分块(Chunk)后,通过 Embedding 模型转化为向量,存储在向量数据库中,以便后续进行语义检索。
如何验收 Skill 的效果,尤其是召回率
验收 Skill 不能只凭感觉,需要量化的工程指标。核心关注以下七点:
- 任务成功率: 加载 Skill 后,任务是否更容易完成(如代码修改是否通过测试)。
- 工具调用成功率: Skill 是否减少了选错工具或参数非法的情况。
- 输出稳定性: 格式错误率、字段缺失率是否下降。
- 人工修正率: 用户对 AI 输出的返工率是否下降。
- Token 消耗: 引入 Skill 后的单任务成本是否可控。
- Skill 命中准确率: 该用的时候有没有用。
- Skill 误召回率(关键): 不该用的时候有没有乱用。误召回非常危险,因为错误的 Skill 会给 Agent 带来错误的执行方向。验收时需通过 A/B 测试,对比引入 Skill 前后这些指标的变化。
Skill 与渐进式披露,以及 Agent 的实现
渐进式披露(Progressive Disclosure)
这是 Skill 高效运行的核心设计哲学。为了避免一次性把所有信息塞进上下文窗口导致 Token 浪费和模型注意力涣散,Skill 采用了三层加载机制:
- 元数据层(始终加载): Agent 启动时,仅加载所有 Skill 的"名片"(名称和一句话描述),让 Agent 知道有哪些能力可用。
- 指令层(按需加载): 当 Agent 判断需要执行某个任务时,才会读取对应的
SKILL.md完整内容。 - 资源层(特定场景加载): 只有在执行过程中真正需要时,才会加载配套的脚本或参考文件。
Agent 的实现
Agent 就像一个熟悉电脑操作的人。它首先根据用户的请求匹配元数据,判断需要哪个 Skill;然后通过工具调用(Function Calling)加载该 Skill 的详细指令;接着按照指令,在沙盒环境中执行脚本或调用 MCP 工具,最终整合结果完成任务。